package com.acceptable.qucun.generic.config;

import com.acceptable.qucun.generic.entity.FileItem;
import com.acceptable.qucun.generic.entity.UrlUserItem;
import com.acceptable.qucun.generic.filter.EncodingFilter;
import com.acceptable.qucun.generic.filter.FormatVerifyFilter;
import com.acceptable.qucun.generic.filter.RedisFilter;
import com.acceptable.qucun.generic.filter.SecretFilter;
import com.acceptable.qucun.generic.security.AuthenFailureHandler;
import com.acceptable.qucun.generic.security.AuthenSuccessHandler;
import com.acceptable.qucun.generic.security.CustomLogoutSuccessHandler;
import com.acceptable.qucun.generic.security.LoginAuthenFilter;
import com.acceptable.qucun.user.service.LoginVerifyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired private AuthenFailureHandler failureHandler;
    @Autowired private LoginVerifyService loginVerify;
    @Autowired private AuthenSuccessHandler successHandler;
    @Autowired private LoginAuthenFilter authenFilter;
    @Autowired private CustomLogoutSuccessHandler logoutSuccessHandler;
    @Autowired private RedisFilter redisFilter;
    @Autowired private  UrlUserItem urlUserItem;

    // 登录 密码加密
    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.userDetailsService(loginVerify).passwordEncoder(passwordEncoder());
//        String password = passwordEncoder().encode("123");
//        auth.inMemoryAuthentication().withUser("arc").password(password).roles("admin");
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and() // 允许spring security被跨源访问
            .formLogin()
            .loginPage(urlUserItem.getLoginPage())
            .usernameParameter("email")
            .passwordParameter("password")
            .loginProcessingUrl("/user/login")  // 处理登录表单数据的uri
//            .defaultSuccessUrl("/user/success")   // 登录成功后的界面 该页面必须通过get方式的请求
            .successHandler(successHandler)
            .failureHandler(failureHandler)
            .and().authorizeRequests()
                // 开发用 测试权限开放 部署时变更
                  .antMatchers(
                          "/user/register", "/user/verify_code", "/user/reset_pwd", "/user/head_img_show",
                          "/share/file_list", "/share/info/**",
                          "/file/enter_dict", "/file/info", "/file/entire_download", "/file/download_exist_check",
                          "/index",
                          "/test").permitAll()
                  .anyRequest()   // 其他任何资源
//                  .hasAuthority("admin")
                  .authenticated() // 未认证情况下都不可访问
//            .and().exceptionHandling().authenticationEntryPoint(entryPoint) //关闭拦截未登录自动跳转,改为返回json信息
            .and().csrf().disable(); //关闭csrf 防跨源攻击关闭

        // 验证前先执行一部分过滤器
        // 解密 ==> 主要数据格式验证 ==> 缓存检测
        // LogoutFilter ==> UsernamePasswordAuthenticationFilter
        http.addFilterBefore(new EncodingFilter(), LogoutFilter.class);
        http.addFilterBefore(new SecretFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(new FormatVerifyFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(redisFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterAt(authenFilter, UsernamePasswordAuthenticationFilter.class);
        http.logout()
            .logoutUrl("/user/logout")
            .logoutSuccessHandler(logoutSuccessHandler);
//            .deleteCookies();
    }
}
